package com.wawei.seeds.utils;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * Template of NotifyHandler for handling the async message from background thread
 * Almost information delivery of async procession between main thread and background thread
 * in this app is done by handler.
 *
 * Get data from remote server (http etc.) is a async task.
 *
 * @param <T>   target of weak reference. it could be a object of activity, fragment
 * @param <E>   type of data from remote server

 */
public abstract class WalnutNotifyHandler<T, E> extends Handler {
    private WeakReference<T> target ;
    public static final int LOAD_NEW_ACHIEVE_DATA = 0x9000;
    public static final int LOAD_OLD_ACHIEVE_DATA = 0x9001;
    public static final int INIT_ACHIEVE_DATA = 0x9002;

    public WalnutNotifyHandler(){}

    public WalnutNotifyHandler(T t){
        this.target = new WeakReference<>(t);
    }

    public void setTarget(T t){
        if(null != target){
            target.clear();
            target = new WeakReference<>(t);
        }
    }

    public T get(){
        return target.get();
    }

    private List<E> extractListFromMessage(Message data){
        Bundle bundle = data.getData();
        Object[] ds = (Object[])bundle.get(RetrofitNetworkService.RESULT_DATA);
        List<E> items = new ArrayList<>(ds.length);
        for(Object e : ds){
            items.add((E)e);
        }
        return items;
    }

    @Override
    public void handleMessage(Message msg) {
        T t = target.get();
        List<E> items;
        if(null != t){
            switch(msg.what){
                case INIT_ACHIEVE_DATA:
                    items = extractListFromMessage(msg);
                    doInitData(t,items);
                    break;
                case LOAD_NEW_ACHIEVE_DATA:
                    items = extractListFromMessage(msg);
                    doNewData(t, items);
                    break;
                case LOAD_OLD_ACHIEVE_DATA:
                    items = extractListFromMessage(msg);
                    doOldData(t, items);
                    break;
                default:
                    handleOtherMessage(msg);
                    break;
            }
        }
        super.handleMessage(msg);
    }

    /**
     * Process the specific logic of data initialization
     * @param t     the template of source
     * @param data  the returned data from remote server
     */
    public abstract void doInitData(T t, List<E> data);

    /**
     * Process the specific logic of inserting new data
     * @param t     the template of source
     * @param data  the returned data from remote server
     */
    public abstract void doNewData(T t, List<E> data);

    /**
     * Process the specific logic of appending old data
     * @param t     the template of source
     * @param data  the returned data from remote server
     */
    public abstract void doOldData(T t, List<E> data);

    /**
     * Process another message
     * @param msg     android message
     */
    public abstract void handleOtherMessage(Message msg);
}
